﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ReportDetailViewModel.cs" company="Spenta Consulting">
//   (c) Copyright 2011
// </copyright>
// <summary>
//   Report detail view model
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Spenta.StreetCare.Silverlight.MVVM.ViewModels
{
    #region Using Directives

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel.DataAnnotations;
    using System.ServiceModel.DomainServices.Client;
    using System.Windows.Browser;
    using System.Windows.Input;
    using GalaSoft.MvvmLight.Command;
    using GalaSoft.MvvmLight.Messaging;
    using Logging;
    using Microsoft.Maps.MapControl;
    using MVVM.Messages;

    using Spenta.StreetCare.Silverlight.MVVM.Validations;

    using StreetCareAPI;

    #endregion

    /// <summary>
    /// Report detail view model
    /// </summary>
    public class ReportDetailViewModel : BaseViewModel
    {
        #region Private members

        /// <summary>
        /// Comment validation scope
        /// </summary>
        private readonly ValidationScope commentValidationScope = new ValidationScope();

        /// <summary>
        /// Private store for the report
        /// </summary>
        private Report report;

        /// <summary>
        /// Private store for the comment
        /// </summary>
        private Core.Models.Comment comment;

        /// <summary>
        /// Private store for the user
        /// </summary>
        private User user;

        /// <summary>
        /// Private store for the user
        /// </summary>
        private Customer customer;

        /// <summary>
        /// Private store for the waiting visible property
        /// </summary>
        private bool waitingVisible;

        /// <summary>
        /// Private store for the report validation errors
        /// </summary>
        private ObservableCollection<ValidationResult> commentValidationErrors = new ObservableCollection<ValidationResult>();

        #endregion

        #region Class Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="ReportDetailViewModel"/> class.
        /// </summary>
        public ReportDetailViewModel()
        {
            this.Comment = new Core.Models.Comment();

            if (HtmlPage.IsEnabled)
            {
                Messenger.Default.Register<OpenReportMessage>(this, m => Report = m.Report);
                Messenger.Default.Register<User>(this, user => User = user);
                Messenger.Default.Register<Customer>(this, customer => Customer = customer);
            }
        }

        #endregion

        #region ViewModel Properties

        /// <summary>
        /// Gets a value indicating whether this <see cref="ReportDetailViewModel"/> is authenticated.
        /// </summary>
        /// <value>
        ///   <c>true</c> if authenticated; otherwise, <c>false</c>.
        /// </value>
        public bool Authenticated
        {
            get
            {
                return this.user != null;
            }
        }

        /// <summary>
        /// Gets or sets the user.
        /// </summary>
        /// <value>
        /// The authenticated user.
        /// </value>
        public User User
        {
            get
            {
                return this.user;
            }

            set
            {
                this.user = value;
                this.RaisePropertyChanged("User");
                this.RaisePropertyChanged("Authenticated");
            }
        }

        /// <summary>
        /// Gets or sets the customer.
        /// </summary>
        /// <value>
        /// The customer.
        /// </value>
        public Customer Customer
        {
            get
            {
                return this.customer;
            }

            set
            {
                this.customer = value;
                this.RaisePropertyChanged("Customer");
            }
        }

        /// <summary>
        /// Gets or sets the view map.
        /// </summary>
        /// <value>The view map.</value>
        public Map ViewMap { get; set; }

        /// <summary>
        /// Gets or sets the report.
        /// </summary>
        /// <value>The report.</value>
        public Report Report
        {
            get
            {
                return this.report;
            }

            set
            {
                this.report = value;
                RaisePropertyChanged("Report");
                this.ViewMap.Center = this.report.ReportMapLocation;
            }
        }

        /// <summary>
        /// Gets or sets the comment.
        /// </summary>
        /// <value>The comment.</value>
        public Core.Models.Comment Comment
        {
            get
            {
                return this.comment;
            }

            set
            {
                this.comment = value;
                RaisePropertyChanged("Comment");
            }
        }

        /// <summary>
        /// Gets the comment validation scope.
        /// </summary>
        /// <value>The comment validation scope.</value>
        public ValidationScope CommentValidationScope
        {
            get
            {
                return this.commentValidationScope;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [waiting visible].
        /// </summary>
        /// <value><c>true</c> if [waiting visible]; otherwise, <c>false</c>.</value>
        public bool WaitingVisible
        {
            get
            {
                return this.waitingVisible;
            }

            set
            {
                this.waitingVisible = value;
                RaisePropertyChanged("WaitingVisible");
            }
        }

        /// <summary>
        /// Gets or sets the comment validation errors.
        /// </summary>
        /// <value>The comment validation errors.</value>
        public ObservableCollection<ValidationResult> CommentValidationErrors
        {
            get
            {
                return this.commentValidationErrors;
            }

            set
            {
                this.commentValidationErrors = value;
                this.RaisePropertyChanged("CommentValidationErrors");
            }
        }

        /// <summary>
        /// Gets the create comment command reference
        /// </summary>
        /// <value>The create comment command.</value>
        public ICommand CreateCommentCommand
        {
            get
            {
                return new RelayCommand(this.CreateComment);
            }
        }

        #endregion

        #region Event Methods

        /// <summary>
        /// Creates the comment completed.
        /// </summary>
        /// <param name="io">The invoke operation.</param>
        private void CreateCommentCompleted(InvokeOperation<Core.Models.Comment> io)
        {
            if (io.HasError)
            {
                LogHelper.Logger.WriteError("Error creating comment" + io.Error.Message);

                // TODO: Handle error
                return;
            }

            this.Comment = new Core.Models.Comment();

            // TODO: Extend RIA Services
            var newComment = new Comment
                {
                    CommentText = io.Value.CommentText,
                    CommentBy = io.Value.CommentBy,
                    CommentFor = io.Value.CommentFor,
                    CommentID = io.Value.CommentID,
                    CommentRating = io.Value.CommentRating,
                    CommentWhen = io.Value.CommentWhen,
                    User = new User
                    {
                        UserID = this.User.UserID,
                        UserIdentityProvider = this.User.UserIdentityProvider,
                        UserImageUrl = this.User.UserImageUrl,
                        UserNameIdentifier = this.User.UserNameIdentifier,
                        UserNickname = this.User.UserNickname
                    },
                    Report = Report
                };

            if (Report.Comments == null)
            {
                Report.Comments = new ObservableCollection<Comment>();    
            }

            Report.Comments.Add(newComment);

            Messenger.Default.Send(new NewCommentCompletedMessage { Comment = newComment });

            this.WaitingVisible = false;
        }

        #endregion

        #region Commands

        /// <summary>
        /// Handles the create comment command.
        /// </summary>
        private void CreateComment()
        {
            this.CommentValidationScope.ValidateScope();

            if (!this.CommentValidationScope.IsValid())
            {
                return;
            }

            this.WaitingVisible = true;

            this.Comment.CommentFor = this.Report.ReportID;
            this.Comment.CommentBy = this.User.UserID;
            this.Comment.CommentWhen = DateTime.Now;

            ApiContext.CreateComment(this.Comment, this.CreateCommentCompleted, null);
        }

        #endregion
    }
}
